<style scoped>

.el-divider--horizontal {
  margin: 12px 0;
}

</style>
<template>
  <div>
    <el-dialog
      title="单元纠察图配置"
      :visible.sync="dialogVisible"
      :close-on-press-escape="false"
      :close-on-click-modal="false"
      width="90%"
      :before-close="clearForm">

      <el-form
        :label-position="labelPosition"
        label-width="80px"
        :model="saveData"
        :rules="rules"
        :inline="true"
        ref="ruleForm"
      >
        <el-form-item label="系统" prop="systemUuid">
          <el-select filterable
                     @change="refreshUseCaseOptions"
                     :disabled="saveData.id && saveData.id !==''" v-model="saveData.systemUuid" placeholder="请选择系统">
            <el-option
              v-for="item in systemOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="用例" prop="useCaseUuid">
          <el-select :disabled="saveData.systemUuid === '' ||(saveData.id && saveData.id !=='')"
                     @change="refreshUnitViewOptions"
                     filterable
                     v-model="saveData.useCaseUuid"
                     placeholder="请选择用例">
            <el-option
              v-for="item in useCaseOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button @click="treeView">纠察图树结构</el-button>
        </el-form-item>
      </el-form>
      <el-divider></el-divider>
      <el-row>
        <rule-tree-list ref="ruleTreeList"></rule-tree-list>
      </el-row>

      <span slot="footer" class="dialog-footer">
    <el-button @click="clearForm">取 消</el-button>
    <el-button type="primary" @click="save">确 定</el-button>
  </span>
    </el-dialog>

    <el-drawer
      title="纠察图树结构"
      size="40%"
      :visible.sync="treeViewFlag"
      :with-header="true">
      <el-tree
        :data="treeData"
        node-key="nodeId"
        :default-expanded-keys="getExpandedKeys()"
        :props="defaultProps">
      </el-tree>
    </el-drawer>
  </div>
</template>
<script>

import {edgeStyleSelector, nodeDataModes, nodeSelector, nodeStyleSelector, nodeTypes, nodeVueSelector, systemSelector, useCaseSelector} from "@/api/loadSelectorApi";
import {remoteValidateUnitViewUnique, unitViewSave} from "@/api/unitView";
import ruleTreeList from "@/views/bic-config/components/ruleTreeList";
import unitViewTree from "@/views/bic-config/unit-view-tree.vue";
import {remoteValidateUnitViewTreeUnique, unitViewTreeSave} from "@/api/unitViewTree";
import fa from "element-ui/src/locale/lang/fa";

export default {
  name: "bicEditForm",
  filters: {},
  components: {
    ruleTreeList
  },
  data() {
    const validateName = async (rule, value, callback) => {
      if (this.saveData.id) {
        callback()
      }
      let systemUuid = this.saveData.systemUuid;
      let useCaseUuid = this.saveData.useCaseUuid;

      if (systemUuid === '') {
        callback(new Error("请选择纠察图所属系统"))
        return;
      }

      if (useCaseUuid === '') {
        callback(new Error("请选择纠察图所属用例"))
        return;
      }

      let ret = await remoteValidateUnitViewTreeUnique(systemUuid, useCaseUuid);
      if (ret.data.result) {
        callback()
      } else {
        callback(new Error("当前系统当前用例已经存在纠察图"))
      }
    };

    return {
      labelPosition: 'right',
      dialogVisible: false,
      saveData: {
        systemUuid: '',
        useCaseUuid: '',
        edges: [],
        nodes: []
      },
      relationModel: [],
      tempRelationModel: [
        {
          sourceNodeUuid: '',
          sourceStyleUuid: '',
          sourceNodeDataKey: '',
          sourceNodeDataMode: '',
          targetNodeUuid: '',
          targetStyleUuid: '',
          targetNodeDataKey: '',
          targetNodeDataMode: '',
          edgeStyleUuid: '',
          hoverName: '',
          children: []
        }
      ],
      rules: {
        systemUuid: [
          {required: true, message: '此项必填', trigger: 'change'},
          {validator: validateName, trigger: 'change'}
        ],
        useCaseUuid: [
          {required: true, message: '此项必填', trigger: 'change'},
          {validator: validateName, trigger: 'change'}
        ],
      },
      systemOptions: [],
      useCaseOptions: [],
      nodeOptions: [],
      nodeVueOptions: [],
      nodeStyleOptions: [],
      edgeStyleOptions: [],
      nodeDataModeOptions: [],
      nodeTypesOptions: [],
      selectors: {
        nodeDataModeOptions: [],
        nodeTypesOptions: [],
        nodeOptions: [],
        nodeVueOptions: [],
        nodeStyleOptions: [],
        edgeStyleOptions: [],
      },
      tempSelectors: {
        nodeDataModeOptions: [],
        nodeTypesOptions: [],
        nodeOptions: [],
        nodeVueOptions: [],
        nodeStyleOptions: [],
        edgeStyleOptions: [],
      },
      treeViewFlag: false,
      treeData: [],
      defaultProps: {
        children: 'children',
        label: 'label'
      },
    };
  },
  async created() {
    this.systemOptions = await systemSelector();
    this.nodeDataModeOptions = await nodeDataModes();
    this.nodeTypesOptions = await nodeTypes();
  },
  mounted() {
  },
  methods: {
    load(data) {
      let vm = this
      if (data) {
        vm.saveData = vm.$cloneObj(data)
      }
      vm.dialogVisible = true

      if (data) {
        vm.reloadView(data)
      } else {
        vm.defaultLoad()
      }
    },
    async reloadView(data) {
      let vm = this

      await vm.selectorLoad()
      vm.relationModel = data.relationModel

      vm.$nextTick(async () => {
        // 组件
        vm.$refs.ruleTreeList.load({relationModel: vm.relationModel, selectors: vm.selectors});
      })
    },
    save() {
      let vm = this
      this.$refs['ruleForm'].validate(async (valid) => {
        if (valid) {
          // 遍历所有节点，进行数据验证
          let relationModel = vm.$refs.ruleTreeList.getRelationModel()
          if (relationModel.length === 0) {
            vm.$message({type: 'error', message: '请至少添加一个节点'});
            return
          }
          vm.loopFillUuid(relationModel)

          if (!vm.loopRelationModelValidate(relationModel)) {
            return
          }

          vm.saveData.relationModel = relationModel
          await vm.doSave(vm.saveData)
        }
      })
    },
    loopRelationModelValidate(relationModel) {
      for (let i = 0; i < relationModel.length; i++) {
        let relationModelItem = relationModel[i];
        if (relationModelItem.sourceNodeUuid === '') {
          this.$message({type: 'error', message: '请设置节点【' + relationModelItem.label + '】的开始节点'});
          return false
        }
        if (relationModelItem.targetNodeUuid === '') {
          this.$message({type: 'error', message: '请设置节点【' + relationModelItem.label + '】的结束节点'});
          return false
        }
        if (relationModelItem.edgeStyleUuid === '') {
          this.$message({type: 'error', message: '请设置节点【' + relationModelItem.label + '】的边样式'});
          return false
        }
        if (relationModelItem.sourceNodeDataMode === '') {
          this.$message({type: 'error', message: '请设置节点【' + relationModelItem.label + '】的开始节点数据模式'});
          return false
        }
        if (relationModelItem.targetNodeDataMode === '') {
          this.$message({type: 'error', message: '请设置节点【' + relationModelItem.label + '】的结束节点数据模式'});
          return false
        }
        if (relationModelItem.sourceNodeDataKey === '') {
          this.$message({type: 'error', message: '请设置节点【' + relationModelItem.label + '】的开始节点数据键'});
          return false
        }
        if (relationModelItem.targetNodeDataKey === '') {
          this.$message({type: 'error', message: '请设置节点【' + relationModelItem.label + '】的结束节点数据键'});
          return false
        }
        if (relationModelItem.children) {
          this.loopRelationModelValidate(relationModelItem.children)
        }
      }
      return true;
    },
    async doSave(saveData) {
      let vm = this
      let ret = await unitViewTreeSave(saveData);
      if (ret.ok) {
        vm.$message({type: 'success', message: '保存成功'});
      } else {
        vm.$message({type: 'error', message: '保存失败：' + ret.message});
      }
      vm.clearForm()
      vm.$parent.query()
    },
    clearForm() {
      let vm = this
      try {
        vm.saveData = {
          systemUuid: '',
          useCaseUuid: '',
          edges: [],
          nodes: []
        }
        vm.relationModel = []
        vm.$refs['ruleForm'].resetFields()
      } catch (e) {
        console.log(e)
      }
      vm.dialogVisible = false
    },
    async refreshUseCaseOptions() {
      let vm = this
      vm.saveData.useCaseUuid = ''
      vm.relationModel = vm.getRelationModel()
      await vm.selectorLoad()
    },
    async selectorLoad() {
      let vm = this
      vm.useCaseOptions = await useCaseSelector(vm.saveData.systemUuid)
      vm.nodeOptions = await nodeSelector(vm.saveData.systemUuid)
      vm.nodeVueOptions = await nodeVueSelector(vm.saveData.systemUuid)
      vm.nodeStyleOptions = await nodeStyleSelector(vm.saveData.systemUuid)
      vm.edgeStyleOptions = await edgeStyleSelector(vm.saveData.systemUuid)
      vm.selectors = vm.getSelectors()
    },
    refreshUnitViewOptions() {
      let vm = this
      vm.relationModel = vm.getRelationModel()
      vm.selectors = vm.getSelectors()
      vm.$nextTick(async () => {
        // 组件
        vm.$refs.ruleTreeList.load({relationModel: vm.relationModel, selectors: vm.selectors});
      })
    },
    defaultLoad() {
      let vm = this
      vm.relationModel = vm.getRelationModel()
      vm.selectors = vm.getEmptySelectors()

      vm.$nextTick(async () => {
        // 组件
        vm.$refs.ruleTreeList.load({relationModel: vm.relationModel, selectors: vm.selectors});
      })
    },
    getRelationModel() {
      return this.$cloneObj(this.tempRelationModel)
    },
    getEmptySelectors() {
      return this.$cloneObj(this.tempSelectors)
    },
    getSelectors() {
      let vm = this
      return {
        nodeDataModeOptions: vm.nodeDataModeOptions,
        nodeTypesOptions: vm.nodeTypesOptions,
        nodeOptions: vm.nodeOptions,
        nodeVueOptions: vm.nodeVueOptions,
        nodeStyleOptions: vm.nodeStyleOptions,
        edgeStyleOptions: vm.edgeStyleOptions,
      }
    },
    treeView() {
      let vm = this
      vm.treeData = vm.$cloneObj(vm.$refs.ruleTreeList.getRelationModel())
      vm.loopFillUuid(vm.treeData)
      vm.treeViewFlag = true
    },
    getExpandedKeys() {
      let vm = this
      let expandedKeys = []
      for (let i = 0; i < vm.treeData.length; i++) {
        expandedKeys.push(vm.treeData[i].nodeId)
        if (vm.treeData[i].children) {
          vm.loopExpandedKeys(expandedKeys, vm.treeData[i].children)
        }
      }
      return expandedKeys;
    },
    loopExpandedKeys(expandedKeys, treeData) {
      let vm = this
      if (treeData) {
        for (let i = 0; i < treeData.length; i++) {
          expandedKeys.push(treeData[i].nodeId)
          if (treeData[i].children) {
            vm.loopExpandedKeys(expandedKeys, treeData[i].children)
          }
        }
      }
    },
    loopFillUuid(obj) {
      for (let i = 0; i < obj.length; i++) {
        obj[i].nodeId = this.guid()
        obj[i].label = this.getLabelName(obj[i])
        if (obj[i].children) {
          this.loopFillUuid(obj[i].children)
        } else {
          obj[i].children = []
        }
      }
    },
    guid() {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
      });
    },
    getLabelName(labelV) {
      let vm = this
      let sourceNodeUuid = labelV.sourceNodeUuid;
      let targetNodeUuid = labelV.targetNodeUuid;
      let sourceName = 'empty-source-name'
      let targetName = 'empty-target-name'
      for (let i = 0; i < vm.nodeOptions.length; i++) {
        let nodeOption = vm.nodeOptions[i];
        if (nodeOption.value === sourceNodeUuid) {
          sourceName = nodeOption.label
        }
        if (nodeOption.value === targetNodeUuid) {
          targetName = nodeOption.label
        }
      }
      return sourceName + " => " + targetName
    }
  }
}
</script>
